/*
Trabalho de Arquitetura

Grupo:
	Rafael Oliveira dos Santos - DRE: 108055848
	Thiago Rodrigues Carvalho - DRE:
	Leandro Rola Belas - DRE:
	Fernando Cavalhosa - DRE:

*/

#include<stdio.h>

int registrador[5];
int ra,rb, rend, rdados, pc, ir;
int pontosControleULA[5];
int pontosControleMUXA[2];
int pontosControleMUXB[3];
int pontosControleREG[5];
int pontoControleRA, pontoControleRB;
int pontoControlePC, pontoControleREnd, pontoControleRDados, pontoControleIR;

class Multiplexador{
    public:
        Multiplexador(){

        }
        int escolheSaidaA(){
            if (pontosControleMUXA[0]==0 && pontosControleMUXA[1]==0)
                return rdados;
            else if(pontosControleMUXA[0]==0 && pontosControleMUXA[1]==1)
                return registrador[0];
            else if(pontosControleMUXA[0]==1 && pontosControleMUXA[1]==0)
                return registrador[1];
            else if(pontosControleMUXA[0]==1 && pontosControleMUXA[1]==1)
                return ra;
        }
        int escolheSaidaB(){
            if (pontosControleMUXB[0]==0 && pontosControleMUXB[1]==0 && pontosControleMUXB[2]==0)
                return pc;
            else if(pontosControleMUXB[0]==0 && pontosControleMUXB[1]==0 && pontosControleMUXB[2]==1)
                return registrador[2];
            else if(pontosControleMUXB[0]==0 && pontosControleMUXB[1]==1 && pontosControleMUXB[2]==0)
                return registrador[3];
            else if(pontosControleMUXB[0]==0 && pontosControleMUXB[1]==1 && pontosControleMUXB[2]==1)
                return registrador[4];
            else if(pontosControleMUXB[0]==1 && pontosControleMUXB[1]==0 && pontosControleMUXB[2]==0)
                return rb;
        }
};

class ULA{
    private:
        Multiplexador a;
	public:
		ULA(){

		}
        int executaOperacao(){
             if(pontosControleULA[0] == 0 && pontosControleULA[1] == 0 && pontosControleULA[2] == 0 && pontosControleULA[3] == 0 && pontosControleULA[4] == 0)
                return a.escolheSaidaA();
             else if(pontosControleULA[0] == 0 && pontosControleULA[1] == 0 && pontosControleULA[2] == 0 && pontosControleULA[3] == 0 && pontosControleULA[4] == 1)
                return a.escolheSaidaB();
             else if(pontosControleULA[0] == 0 && pontosControleULA[1] == 0 && pontosControleULA[2] == 0 && pontosControleULA[3] == 1 && pontosControleULA[4] == 0)
                return a.escolheSaidaA() + a.escolheSaidaB();
        }
};

class UnidadeControle{
    private:
        ULA ula;
        int resultado;
	public:
		UnidadeControle(){

		}
		void zeraRegistradores(){
            for(int i = 0; i < 5; i++)
                pontosControleREG[i] = 0;
            pontoControleIR = 0;
            pontoControlePC = 0;
            pontoControleRA = 0;
            pontoControleRB = 0;
            pontoControleRDados = 0;
            pontoControleREnd = 0;
		}

		void carregaRegistradores(int resultado){
            for(int i = 0; i < 5; i++){
                if(pontosControleREG[i] == 1){
                    registrador[i] = resultado;
                }
            }
            if(pontoControleIR==1)     ir = resultado;
            if(pontoControlePC==1)     pc = resultado;
            if(pontoControleRA==1)     ra = resultado;
            if(pontoControleRB==1)     rb = resultado;
            if(pontoControleRDados==1) rdados = resultado;
            if(pontoControleREnd==1)   rend = resultado;
        }

		void executaOperacao(char *linha){
			if(linha == "add r0,r1"){
                executaOperacao("mov rb,r1");
                executaOperacao("add r0,rb");
			}
			else if(linha == "mov rb,r0"){
                pontosControleULA = {0,0,0,0,0};
                pontosControleMUXA = {0,1};
                resultado = ula.executaOperacao();
                pontoControleRB = 1;
                carregaRegistradores(resultado);
                zeraRegistradores();
                printf("%d\n", resultado);
			}
			else if(linha == "mov rb,r1"){
                pontosControleULA = {0,0,0,0,0};
                pontosControleMUXA = {1,0};
                resultado = ula.executaOperacao();
                pontoControleRB = 1;
                carregaRegistradores(resultado);
                zeraRegistradores();
                printf("%d\n", resultado);
			}
			else if(linha == "add r0,r2"){
			    pontosControleULA = {0,0,0,1,0};
			    pontosControleMUXA = {0,1};
			    pontosControleMUXB = {0,0,1};
                resultado = ula.executaOperacao();
                pontosControleREG[0]=1;
                carregaRegistradores(resultado);
                zeraRegistradores();
                printf("%d\n", resultado);
			}
			else if(linha == "add r0,rb"){
                pontosControleULA = {0,0,0,1,0};
                pontosControleMUXA = {0,1};
                pontosControleMUXB = {1,0,0};
                resultado = ula.executaOperacao();
                pontosControleREG[0]=1;
                carregaRegistradores(resultado);
                zeraRegistradores();
                printf("%d\n", resultado);
			}
        }
};

int main(){

	registrador[0]=10;
	registrador[1]=5;
	registrador[2]=2;
	UnidadeControle uc;
	uc.executaOperacao("add r0,r2");
	uc.executaOperacao("mov rb,r0");
	uc.executaOperacao("mov rb,r1");
	uc.executaOperacao("add r0,r1");
	return 0;

}
